home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gsfunc4.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  19.2 KB  |  766 lines

  1. /* Copyright (C) 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gsfunc4.c,v 1.3 2000/09/19 19:00:28 lpd Exp $ */
  20. /* Implementation of FunctionType 4 (PostScript Calculator) Functions */
  21. #include "math_.h"
  22. #include "memory_.h"
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gsdsrc.h"
  26. #include "gsfunc4.h"
  27. #include "gxfarith.h"
  28. #include "gxfunc.h"
  29. #include "stream.h"
  30. #include "strimpl.h"
  31. #include "sfilter.h"        /* for SubFileDecode */
  32. #include "spprint.h"
  33.  
  34. typedef struct gs_function_PtCr_s {
  35.     gs_function_head_t head;
  36.     gs_function_PtCr_params_t params;
  37.     /* Define a bogus DataSource for get_function_info. */
  38.     gs_data_source_t data_source;
  39. } gs_function_PtCr_t;
  40.  
  41. /* GC descriptor */
  42. private_st_function_PtCr();
  43.  
  44. /* Define the maximum stack depth. */
  45. #define MAX_VSTACK 100        /* per documentation */
  46.  
  47. /* Define the structure of values on the stack. */
  48. typedef enum {
  49.     CVT_NONE = 0,    /* empty stack slot */
  50.     CVT_BOOL,
  51.     CVT_INT,
  52.     CVT_FLOAT
  53. } calc_value_type_t;
  54. typedef struct calc_value_s {
  55.     calc_value_type_t type;
  56.     union {
  57.     int i;            /* also used for Boolean */
  58.     float f;
  59.     } value;
  60. } calc_value_t;
  61.  
  62. /* Store a float. */
  63. private void
  64. store_float(calc_value_t *vsp, floatp f)
  65. {
  66.     vsp->value.f = f;
  67.     vsp->type = CVT_FLOAT;
  68. }
  69.  
  70. /*
  71.  * Define extended opcodes with typed operands.  We use the original
  72.  * opcodes for the floating-point case.
  73.  */
  74. typedef enum {
  75.  
  76.     /* Typed variants */
  77.  
  78.     PtCr_abs_int = PtCr_NUM_OPCODES,
  79.     PtCr_add_int,
  80.     PtCr_mul_int,
  81.     PtCr_neg_int,
  82.     PtCr_not_bool,        /* default is int */
  83.     PtCr_sub_int,
  84.     PtCr_eq_int,
  85.     PtCr_ge_int,
  86.     PtCr_gt_int,
  87.     PtCr_le_int,
  88.     PtCr_lt_int,
  89.     PtCr_ne_int,
  90.  
  91.     /* Coerce and re-dispatch */
  92.  
  93.     PtCr_int_to_float,
  94.     PtCr_2nd_int_to_float,
  95.     PtCr_int2_to_float,
  96.  
  97.     /* Miscellaneous */
  98.  
  99.     PtCr_no_op,
  100.     PtCr_typecheck
  101.  
  102. } gs_PtCr_typed_opcode_t;
  103.  
  104. /* Evaluate a PostScript Calculator function. */
  105. private int
  106. fn_PtCr_evaluate(const gs_function_t *pfn_common, const float *in, float *out)
  107. {
  108.     const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
  109.     calc_value_t vstack[1 + MAX_VSTACK + 1];
  110.     calc_value_t *vsp = vstack + pfn->params.m;
  111.     const byte *p = pfn->params.ops.data;
  112.     int i;
  113.  
  114.     /*
  115.      * Define the table for mapping explicit opcodes to typed opcodes.
  116.      * We index this table with the opcode and the types of the top 2
  117.      * values on the stack.
  118.      */
  119.     static const struct op_defn_s {
  120.     byte opcode[16];    /* 4 * type[-1] + type[0] */
  121.     } op_defn_table[] = {
  122.     /* Keep this consistent with opcodes in gsfunc4.h! */
  123.  
  124. #define O4(op) op,op,op,op
  125. #define E PtCr_typecheck
  126. #define E4 O4(E)
  127. #define N PtCr_no_op
  128.     /* 0-operand operators */
  129. #define OP_NONE(op)\
  130.   {{O4(op), O4(op), O4(op), O4(op)}}
  131.     /* 1-operand operators */
  132. #define OP1(b, i, f)\
  133.   {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
  134. #define OP_NUM1(i, f)\
  135.   OP1(E, i, f)
  136. #define OP_MATH1(f)\
  137.   OP1(E, PtCr_int_to_float, f)
  138. #define OP_ANY1(op)\
  139.   OP1(op, op, op)
  140.     /* 2-operand operators */
  141. #define OP_NUM2(i, f)\
  142.   {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
  143. #define OP_INT_BOOL2(i)\
  144.   {{E4, E,i,i,E, E,i,i,E, E4}}
  145. #define OP_MATH2(f)\
  146.   {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
  147.     E,E,PtCr_int_to_float,f}}
  148. #define OP_INT2(i)\
  149.   {{E4, E4, E,E,i,E, E4}}
  150. #define OP_REL2(i, f)\
  151.   {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
  152. #define OP_ANY2(op)\
  153.   {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
  154.  
  155.     /* Arithmetic operators */
  156.  
  157.     OP_NUM1(PtCr_abs_int, PtCr_abs),    /* abs */
  158.     OP_NUM2(PtCr_add_int, PtCr_add),    /* add */
  159.     OP_INT_BOOL2(PtCr_and),  /* and */
  160.     OP_MATH2(PtCr_atan),    /* atan */
  161.     OP_INT2(PtCr_bitshift),    /* bitshift */
  162.     OP_NUM1(N, PtCr_ceiling),    /* ceiling */
  163.     OP_MATH1(PtCr_cos),    /* cos */
  164.     OP_NUM1(N, PtCr_cvi),    /* cvi */
  165.     OP_NUM1(PtCr_int_to_float, N),    /* cvr */
  166.     OP_MATH2(PtCr_div),    /* div */
  167.     OP_MATH2(PtCr_exp),    /* exp */
  168.     OP_NUM1(N, PtCr_floor),    /* floor */
  169.     OP_INT2(PtCr_idiv),    /* idiv */
  170.     OP_MATH1(PtCr_ln),    /* ln */
  171.     OP_MATH1(PtCr_log),    /* log */
  172.     OP_INT2(PtCr_mod),    /* mod */
  173.     OP_NUM2(PtCr_mul_int, PtCr_mul),    /* mul */
  174.     OP_NUM1(PtCr_neg_int, PtCr_neg),    /* neg */
  175.     OP1(PtCr_not, PtCr_not, E),    /* not */
  176.     OP_INT_BOOL2(PtCr_or),  /* or */
  177.     OP_NUM1(N, PtCr_round),    /* round */
  178.     OP_MATH1(PtCr_sin),    /* sin */
  179.     OP_MATH1(PtCr_sqrt),    /* sqrt */
  180.     OP_NUM2(PtCr_sub_int, PtCr_sub),    /* sub */
  181.     OP_NUM1(N, PtCr_truncate),    /* truncate */
  182.     OP_INT_BOOL2(PtCr_xor),  /* xor */
  183.  
  184.     /* Comparison operators */
  185.  
  186.     OP_REL2(PtCr_eq_int, PtCr_eq),    /* eq */
  187.     OP_NUM2(PtCr_ge_int, PtCr_ge),    /* ge */
  188.     OP_NUM2(PtCr_gt_int, PtCr_gt),    /* gt */
  189.     OP_NUM2(PtCr_le_int, PtCr_le),    /* le */
  190.     OP_NUM2(PtCr_lt_int, PtCr_lt),    /* lt */
  191.     OP_REL2(PtCr_ne_int, PtCr_ne),    /* ne */
  192.  
  193.     /* Stack operators */
  194.  
  195.     OP1(E, PtCr_copy, E),    /* copy */
  196.     OP_ANY1(PtCr_dup),    /* dup */
  197.     OP_ANY2(PtCr_exch),    /* exch */
  198.     OP1(E, PtCr_index, E),    /* index */
  199.     OP_ANY1(PtCr_pop),    /* pop */
  200.     OP_INT2(PtCr_roll),    /* roll */
  201.  
  202.     /* Constants */
  203.  
  204.     OP_NONE(PtCr_byte),        /* byte */
  205.     OP_NONE(PtCr_int),        /* int */
  206.     OP_NONE(PtCr_float),        /* float */
  207.     OP_NONE(PtCr_true),        /* true */
  208.     OP_NONE(PtCr_false),        /* false */
  209.  
  210.     /* Special */
  211.  
  212.     OP1(PtCr_if, E, E),        /* if */
  213.     OP_NONE(PtCr_else),        /* else */
  214.     OP_NONE(PtCr_return)        /* return */
  215.  
  216.     };
  217.  
  218.     vstack[0].type = CVT_NONE;    /* catch underflow */
  219.     for (i = 0; i < pfn->params.m; ++i)
  220.     store_float(&vstack[i + 1], in[i]);
  221.  
  222.     for (; ; ) {
  223.     int code, n;
  224.  
  225.     sw:
  226.     switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
  227.  
  228.         /* Miscellaneous */
  229.  
  230.     case PtCr_no_op:
  231.         continue;
  232.     case PtCr_typecheck:
  233.         return_error(gs_error_typecheck);
  234.  
  235.         /* Coerce and re-dispatch */
  236.  
  237.     case PtCr_int_to_float:
  238.         store_float(vsp, (floatp)vsp->value.i);
  239.         --p; goto sw;
  240.     case PtCr_int2_to_float:
  241.         store_float(vsp, (floatp)vsp->value.i);
  242.     case PtCr_2nd_int_to_float:
  243.         store_float(vsp - 1, (floatp)vsp[-1].value.i);
  244.         --p; goto sw;
  245.  
  246.         /* Arithmetic operators */
  247.  
  248.     case PtCr_abs_int:
  249.         if (vsp->value.i < 0)
  250.         goto neg_int;
  251.         continue;
  252.     case PtCr_abs:
  253.         vsp->value.f = fabs(vsp->value.f);
  254.         continue;
  255.     case PtCr_add_int: {
  256.         int int1 = vsp[-1].value.i, int2 = vsp->value.i;
  257.  
  258.         if ((int1 ^ int2) >= 0 && ((int1 + int2) ^ int1) < 0)
  259.         store_float(vsp - 1, (double)int1 + int2);
  260.         else
  261.         vsp[-1].value.i = int1 + int2;
  262.         --vsp; continue;
  263.     }
  264.     case PtCr_add:
  265.         vsp[-1].value.f += vsp->value.f;
  266.         --vsp; continue;
  267.     case PtCr_and:
  268.         vsp[-1].value.i &= vsp->value.i;
  269.         --vsp; continue;
  270.     case PtCr_atan: {
  271.         double result;
  272.  
  273.         code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
  274.                     &result);
  275.         if (code < 0)
  276.         return code;
  277.         vsp[-1].value.f = result;
  278.         --vsp; continue;
  279.     }
  280.     case PtCr_bitshift:
  281. #define MAX_SHIFT (ARCH_SIZEOF_INT * 8 - 1)
  282.         if (vsp->value.i < -MAX_SHIFT || vsp->value.i > MAX_SHIFT)
  283.         vsp[-1].value.i = 0;
  284. #undef MAX_SHIFT
  285.         else if ((n = vsp->value.i) < 0)
  286.         vsp[-1].value.i = ((uint)(vsp[-1].value.i)) >> -n;
  287.         else
  288.         vsp[-1].value.i <<= n;
  289.         --vsp; continue;
  290.     case PtCr_ceiling:
  291.         vsp->value.f = ceil(vsp->value.f);
  292.         continue;
  293.     case PtCr_cos:
  294.         vsp->value.f = cos(vsp->value.f);
  295.         continue;
  296.     case PtCr_cvi:
  297.         vsp->value.i = (int)(vsp->value.f);
  298.         vsp->type = CVT_INT;
  299.         continue;
  300.     case PtCr_cvr:
  301.         continue;    /* prepare handled it */
  302.     case PtCr_div:
  303.         if (vsp->value.f == 0)
  304.         return_error(gs_error_undefinedresult);
  305.         vsp[-1].value.f /= vsp->value.f;
  306.         --vsp; continue;
  307.     case PtCr_exp:
  308.         vsp[-1].value.f = pow(vsp[-1].value.f, vsp->value.f);
  309.         --vsp; continue;
  310.     case PtCr_floor:
  311.         vsp->value.f = floor(vsp->value.f);
  312.         continue;
  313.     case PtCr_idiv:
  314.         if (vsp->value.i == 0)
  315.         return_error(gs_error_undefinedresult);
  316.         if ((vsp[-1].value.i /= vsp->value.i) == min_int &&
  317.         vsp->value.i == -1)  /* anomalous boundary case, fail */
  318.         return_error(gs_error_rangecheck);
  319.         --vsp; continue;
  320.     case PtCr_ln:
  321.         vsp->value.f = log(vsp->value.f);
  322.         continue;
  323.     case PtCr_log:
  324.         vsp->value.f = log10(vsp->value.f);
  325.         continue;
  326.     case PtCr_mod:
  327.         if (vsp->value.i == 0)
  328.         return_error(gs_error_undefinedresult);
  329.         vsp[-1].value.i %= vsp->value.i;
  330.         --vsp; continue;
  331.     case PtCr_mul_int: {
  332.         /* We don't bother to optimize this. */
  333.         double prod = (double)vsp[-1].value.i * vsp->value.i;
  334.  
  335.         if (prod < min_int || prod > max_int)
  336.         store_float(vsp - 1, prod);
  337.         else
  338.         vsp[-1].value.i = (int)prod;
  339.         --vsp; continue;
  340.     }
  341.     case PtCr_mul:
  342.         vsp[-1].value.f *= vsp->value.f;
  343.         --vsp; continue;
  344.     case PtCr_neg_int:
  345.     neg_int:
  346.         if (vsp->value.i == min_int)
  347.         store_float(vsp, (floatp)vsp->value.i); /* =self negated */
  348.         else
  349.         vsp->value.i = -vsp->value.i;
  350.         continue;
  351.     case PtCr_neg:
  352.         vsp->value.f = -vsp->value.f;
  353.         continue;
  354.     case PtCr_not_bool:
  355.         vsp->value.i = !vsp->value.i;
  356.         continue;
  357.     case PtCr_not:
  358.         vsp->value.i = ~vsp->value.i;
  359.         continue;
  360.     case PtCr_or:
  361.         vsp[-1].value.i |= vsp->value.i;
  362.         --vsp; continue;
  363.     case PtCr_round:
  364.         vsp->value.f = floor(vsp->value.f + 0.5);
  365.         continue;
  366.     case PtCr_sin:
  367.         vsp->value.f = sin(vsp->value.f);
  368.         continue;
  369.     case PtCr_sqrt:
  370.         vsp->value.f = sqrt(vsp->value.f);
  371.         continue;
  372.     case PtCr_sub_int: {
  373.         int int1 = vsp[-1].value.i, int2 = vsp->value.i;
  374.  
  375.         if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
  376.         store_float(vsp - 1, (double)int1 - int2);
  377.         else
  378.         vsp[-1].value.i = int1 - int2;
  379.         --vsp; continue;
  380.     }
  381.     case PtCr_sub:
  382.         vsp[-1].value.f -= vsp->value.f;
  383.         --vsp; continue;
  384.     case PtCr_truncate:
  385.         vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
  386.                 floor(vsp->value.f));
  387.         continue;
  388.     case PtCr_xor:
  389.         vsp[-1].value.i ^= vsp->value.i;
  390.         --vsp; continue;
  391.  
  392.         /* Boolean operators */
  393.  
  394. #define DO_REL(rel, m)\
  395.   vsp[-1].value.i = vsp[-1].value.m rel vsp->value.m
  396.  
  397.     case PtCr_eq_int:
  398.         DO_REL(==, i);
  399.         goto rel;
  400.     case PtCr_eq:
  401.         DO_REL(==, f);
  402.     rel:
  403.         vsp[-1].type = CVT_BOOL;
  404.         --vsp; continue;
  405.     case PtCr_ge_int:
  406.         DO_REL(>=, i);
  407.         goto rel;
  408.     case PtCr_ge:
  409.         DO_REL(>=, f);
  410.         goto rel;
  411.     case PtCr_gt_int:
  412.         DO_REL(>, i);
  413.         goto rel;
  414.     case PtCr_gt:
  415.         DO_REL(>, f);
  416.         goto rel;
  417.     case PtCr_le_int:
  418.         DO_REL(<=, i);
  419.         goto rel;
  420.     case PtCr_le:
  421.         DO_REL(<=, f);
  422.         goto rel;
  423.     case PtCr_lt_int:
  424.         DO_REL(<, i);
  425.         goto rel;
  426.     case PtCr_lt:
  427.         DO_REL(<, f);
  428.         goto rel;
  429.     case PtCr_ne_int:
  430.         DO_REL(!=, i);
  431.         goto rel;
  432.     case PtCr_ne:
  433.         DO_REL(!=, f);
  434.         goto rel;
  435.  
  436. #undef DO_REL
  437.  
  438.         /* Stack operators */
  439.  
  440.     case PtCr_copy:
  441.         i = vsp->value.i;
  442.         n = vsp - vstack;
  443.         if (i < 0 || i >= n)
  444.         return_error(gs_error_rangecheck);
  445.         if (i > MAX_VSTACK - (n - 1))
  446.         return_error(gs_error_limitcheck);
  447.         memcpy(vsp, vsp - i, i * sizeof(*vsp));
  448.         vsp += i - 1;
  449.         continue;
  450.     case PtCr_dup:
  451.         vsp[1] = *vsp;
  452.         goto push;
  453.     case PtCr_exch:
  454.         vstack[MAX_VSTACK] = *vsp;
  455.         *vsp = vsp[-1];
  456.         vsp[-1] = vstack[MAX_VSTACK];
  457.         continue;
  458.     case PtCr_index:
  459.         i = vsp->value.i;
  460.         if (i < 0 || i >= vsp - vstack - 1)
  461.         return_error(gs_error_rangecheck);
  462.         *vsp = vsp[-i - 1];
  463.         continue;
  464.     case PtCr_pop:
  465.         --vsp;
  466.         continue;
  467.     case PtCr_roll:
  468.         n = vsp[-1].value.i;
  469.         i = vsp->value.i;
  470.         if (n < 0 || n > vsp - vstack - 2)
  471.         return_error(gs_error_rangecheck);
  472.         /* We don't bother to do this efficiently. */
  473.         for (; i > 0; i--) {
  474.         memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
  475.         vsp[-(n + 1)] = vsp[-1];
  476.         }
  477.         for (; i < 0; i++) {
  478.         vsp[-1] = vsp[-(n + 1)];
  479.         memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
  480.         }
  481.         vsp -= 2;
  482.         continue;
  483.  
  484.         /* Constants */
  485.  
  486.     case PtCr_byte:
  487.         vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
  488.         goto push;
  489.     case PtCr_int /* native */:
  490.         memcpy(&vsp[1].value.i, p, sizeof(int));
  491.         vsp[1].type = CVT_INT;
  492.         p += sizeof(int);
  493.         goto push;
  494.     case PtCr_float /* native */:
  495.         memcpy(&vsp[1].value.f, p, sizeof(float));
  496.         vsp[1].type = CVT_FLOAT;
  497.         p += sizeof(float);
  498.         goto push;
  499.     case PtCr_true:
  500.         vsp[1].value.i = true, vsp[1].type = CVT_BOOL;
  501.         goto push;
  502.     case PtCr_false:
  503.         vsp[1].value.i = false, vsp[1].type = CVT_BOOL;
  504.     push:
  505.         if (vsp == &vstack[MAX_VSTACK])
  506.         return_error(gs_error_limitcheck);
  507.         ++vsp;
  508.         continue;
  509.  
  510.         /* Special */
  511.  
  512.     case PtCr_if:
  513.         if ((vsp--)->value.i) {    /* value is true, execute body */
  514.         p += 2;
  515.         continue;
  516.         }
  517.         /* falls through */
  518.     case PtCr_else:
  519.         p += 2 + (p[0] << 8) + p[1];
  520.         continue;
  521.     case PtCr_return:
  522.         goto fin;
  523.     }
  524.     }
  525.  fin:
  526.  
  527.     if (vsp != vstack + pfn->params.n)
  528.     return_error(gs_error_rangecheck);
  529.     for (i = 0; i < pfn->params.n; ++i) {
  530.     switch (vstack[i + 1].type) {
  531.     case CVT_INT:
  532.         out[i] = vstack[i + 1].value.i;
  533.         break;
  534.     case CVT_FLOAT:
  535.         out[i] = vstack[i + 1].value.f;
  536.         break;
  537.     default:
  538.         return_error(gs_error_typecheck);
  539.     }
  540.     }
  541.     return 0;
  542. }
  543.  
  544. /* Test whether a PostScript Calculator function is monotonic. */
  545. private int
  546. fn_PtCr_is_monotonic(const gs_function_t * pfn_common,
  547.              const float *lower, const float *upper,
  548.              gs_function_effort_t effort)
  549. {
  550.     /*
  551.      * No reasonable way to tell.  Eventually we should check for
  552.      * functions consisting of only stack-manipulating operations,
  553.      * since these may be common for DeviceN color spaces and *are*
  554.      * monotonic.
  555.      */
  556.     return 0;
  557. }
  558.  
  559. /* Write the function definition in symbolic form on a stream. */
  560. private int
  561. calc_put_ops(stream *s, const byte *ops, uint size)
  562. {
  563.     const byte *p;
  564.  
  565.     spputc(s, '{');
  566.     for (p = ops; p < ops + size; )
  567.     switch (*p++) {
  568.     case PtCr_byte:
  569.         pprintd1(s, "%d ", *p++);
  570.         break;
  571.     case PtCr_int: {
  572.         int i;
  573.  
  574.         memcpy(&i, p, sizeof(int));
  575.         pprintd1(s, "%d ", i);
  576.         p += sizeof(int);
  577.         break;
  578.     }
  579.     case PtCr_float: {
  580.         float f;
  581.  
  582.         memcpy(&f, p, sizeof(float));
  583.         pprintg1(s, "%g ", f);
  584.         p += sizeof(float);
  585.         break;
  586.     }
  587.     case PtCr_true:
  588.         pputs(s, "true ");
  589.         break;
  590.     case PtCr_false:
  591.         pputs(s, "false ");
  592.         break;
  593.     case PtCr_if: {
  594.         int skip = (p[0] << 8) + p[1];
  595.         int code;
  596.  
  597.         code = calc_put_ops(s, p += 2, skip);
  598.         p += skip;
  599.         if (code < 0)
  600.         return code;
  601.         if (code > 0) {    /* else */
  602.         skip = (p[-2] << 8) + p[-1];
  603.         code = calc_put_ops(s, p, skip);
  604.         p += skip;
  605.         if (code < 0)
  606.             return code;
  607.         pputs(s, " ifelse ");
  608.         } else
  609.         pputs(s, " if ");
  610.     }
  611.     case PtCr_else:
  612.         if (p != ops + size - 2)
  613.         return_error(gs_error_rangecheck);
  614.         return 1;
  615.     /*case PtCr_return:*/    /* not possible */
  616.     default: {        /* must be < PtCr_NUM_OPS */
  617.         static const char *const op_names[] = {
  618.             /* Keep this consistent with opcodes in gsfunc4.h! */
  619.             "abs", "add", "and", "atan", "bitshift",
  620.             "ceiling", "cos", "cvi", "cvr", "div", "exp",
  621.             "floor", "idiv", "ln", "log", "mod", "mul",
  622.             "neg", "not", "or", "round", "sin", "sqrt", "sub",
  623.             "truncate", "xor",
  624.             "eq", "ge", "gt", "le", "lt", "ne",
  625.             "copy", "dup", "exch", "index", "pop", "roll"
  626.         };
  627.  
  628.         pprints1(s, "%s ", op_names[p[-1]]);
  629.         }
  630.     }
  631.     spputc(s, '}');
  632.     return 0;
  633. }
  634. private int
  635. calc_put(stream *s, const gs_function_PtCr_t *pfn)
  636. {
  637.     calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
  638.     return 0;
  639. }
  640.  
  641. /* Access the symbolic definition as a DataSource. */
  642. private int
  643. calc_access(const gs_data_source_t *psrc, ulong start, uint length,
  644.         byte *buf, const byte **ptr)
  645. {
  646.     const gs_function_PtCr_t *const pfn =
  647.     (const gs_function_PtCr_t *)
  648.       ((const char *)psrc - offset_of(gs_function_PtCr_t, data_source));
  649.     stream_SFD_state st;
  650.     stream s;
  651.     const stream_template *const template = &s_SFD_template;
  652.  
  653.     template->set_defaults((stream_state *)&st);
  654.     st.skip_count = start;
  655.     swrite_string(&s, buf, length);
  656.     s.procs.process = template->process;
  657.     s.state = (stream_state *)&st;
  658.     if (template->init)
  659.     template->init((stream_state *)&st);
  660.     calc_put(&s, pfn);
  661.     if (ptr)
  662.     *ptr = buf;
  663.     return 0;
  664. }
  665.  
  666. /* Return PostScript Calculator function information. */
  667. private void
  668. fn_PtCr_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
  669. {
  670.     const gs_function_PtCr_t *const pfn =
  671.     (const gs_function_PtCr_t *)pfn_common;
  672.  
  673.     gs_function_get_info_default(pfn_common, pfi);
  674.     pfi->DataSource = &pfn->data_source;
  675.     {
  676.     stream s;
  677.  
  678.     swrite_position_only(&s);
  679.     calc_put(&s, pfn);
  680.     pfi->data_size = stell(&s);
  681.     }
  682. }
  683.  
  684. /* Free the parameters of a PostScript Calculator function. */
  685. void
  686. gs_function_PtCr_free_params(gs_function_PtCr_params_t * params, gs_memory_t * mem)
  687. {
  688.     gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
  689.     fn_common_free_params((gs_function_params_t *) params, mem);
  690. }
  691.  
  692. /* Allocate and initialize a PostScript Calculator function. */
  693. int
  694. gs_function_PtCr_init(gs_function_t ** ppfn,
  695.           const gs_function_PtCr_params_t * params, gs_memory_t * mem)
  696. {
  697.     static const gs_function_head_t function_PtCr_head = {
  698.     function_type_PostScript_Calculator,
  699.     {
  700.         (fn_evaluate_proc_t) fn_PtCr_evaluate,
  701.         (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
  702.         (fn_get_info_proc_t) fn_PtCr_get_info,
  703.         (fn_get_params_proc_t) fn_common_get_params,
  704.         (fn_free_params_proc_t) gs_function_PtCr_free_params,
  705.         fn_common_free
  706.     }
  707.     };
  708.     int code;
  709.  
  710.     *ppfn = 0;            /* in case of error */
  711.     code = fn_check_mnDR((const gs_function_params_t *)params,
  712.              params->m, params->n);
  713.     if (code < 0)
  714.     return code;
  715.     if (params->m > MAX_VSTACK || params->n > MAX_VSTACK)
  716.     return_error(gs_error_limitcheck);
  717.     /*
  718.      * Pre-validate the operation string to reduce evaluation overhead.
  719.      */
  720.     {
  721.     const byte *p = params->ops.data;
  722.  
  723.     for (; *p != PtCr_return; ++p)
  724.         switch ((gs_PtCr_opcode_t)*p) {
  725.         case PtCr_byte:
  726.         ++p; break;
  727.         case PtCr_int:
  728.         p += sizeof(int); break;
  729.         case PtCr_float:
  730.         p += sizeof(float); break;
  731.         case PtCr_if:
  732.         case PtCr_else:
  733.         p += 2;
  734.         case PtCr_true:
  735.         case PtCr_false:
  736.         break;
  737.         default:
  738.         if (*p >= PtCr_NUM_OPS)
  739.             return_error(gs_error_rangecheck);
  740.         }
  741.     if (p != params->ops.data + params->ops.size - 1)
  742.         return_error(gs_error_rangecheck);
  743.     }
  744.     {
  745.     gs_function_PtCr_t *pfn =
  746.         gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
  747.                 "gs_function_PtCr_init");
  748.  
  749.     if (pfn == 0)
  750.         return_error(gs_error_VMerror);
  751.     pfn->params = *params;
  752.     /*
  753.      * We claim to have a DataSource, in order to write the function
  754.      * definition in symbolic form for embedding in PDF files.
  755.      * ****** THIS IS A HACK. ******
  756.      */
  757.     data_source_init_string2(&pfn->data_source, NULL, 0);
  758.     pfn->data_source.access = calc_access;
  759.     pfn->head = function_PtCr_head;
  760.     pfn->head.is_monotonic =
  761.         fn_domain_is_monotonic((gs_function_t *)pfn, EFFORT_MODERATE);
  762.     *ppfn = (gs_function_t *) pfn;
  763.     }
  764.     return 0;
  765. }
  766.